/**
  ETFRoot project, Anyang Normal University && IMP-CAS

  \class ETFHPTDCChannel
  \brief the class holding the timing data acquired by the HPTDC (@CERN) chip
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-09-27
  \date 2021-10-10 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date        <th>Author      <th>Description                    </tr>
  <tr>  <td>2021-09-27   <td>Asia Sun    <td>file created                   </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <cmath>
#include <iostream>
#include <iomanip>
#include "ETFHPTDCChannel.h"
#include "ETFMsg.h"
#include "ETFMath.h"

using std::cout;
using std::endl;

ClassImp(ETFHPTDCChannel);

/// time for one channel of HPTDC HIGH resolution mode: ~100ps
const double ETFHPTDCChannel::kH_BLIP = 25. / pow(2., 8.);
/// time for one channel of HPTDC VERY HIGH resolution mode: ~25ps
const double ETFHPTDCChannel::kV_BLIP = 25. / pow(2., 10.);

ETFHPTDCChannel::ETFHPTDCChannel() : ETFRawChannel(){
  Initialize();
} // end ctor

ETFHPTDCChannel::ETFHPTDCChannel(const ETFHPTDCChannel &ch) : ETFRawChannel(ch)
,vl(ch.vl), vt(ch.vt) ,fIs_V(ch.fIs_V){}

ETFHPTDCChannel::~ETFHPTDCChannel(){}

void ETFHPTDCChannel::Initialize(){
  Reset();
} // end member function Initialize

double ETFHPTDCChannel::GetLeadingEdge(int i) const{
  if(i < 0 || i >= vl.size())
    ETFMsg::Error("ETFHPTDCChannel", "GetLeadingEdge: i = %d out of bounds", i);
  return vl[i];
} // end member function GetLeadingEdge

double ETFHPTDCChannel::GetTrailingEdge(int i) const{
  if(i < 0 || i >= vt.size())
    ETFMsg::Error("ETFHPTDCChannel", "GetTrailingEdge: i = %d out of bounds", i);
  return vt[i];
} // end member function GetTrailingEdge

void ETFHPTDCChannel::Reset(){
  ETFRawChannel::Reset();
  vl.clear(); vt.clear();
  fIs_V = kFALSE;
} // end member function Reset

void ETFHPTDCChannel::AddLeadingEdgeV(int l){
  fIs_V = true;
  AddLed((l+rand0_1())*kV_BLIP);
} // end member function AddLeadingEdgeV
void ETFHPTDCChannel::AddLeadingEdgeH(int l){
  fIs_V = false;
  AddLed((l+rand0_1())*kH_BLIP);
} // end member function AddLeadingEdgeH
void ETFHPTDCChannel::AddTrailingEdgeV(int t){
  fIs_V = true;
  AddTed((t+rand0_1())*kV_BLIP);
} // end member function AddTrailingEdgeV

void ETFHPTDCChannel::AddTrailingEdgeH(int t){
  fIs_V = false;
  AddTed((t+rand0_1())*kH_BLIP);
} // end member function AddTrailingEdgeH

// add a leading edge
void ETFHPTDCChannel::AddLed(double l){
  vl.push_back(l);
} // end member function AddLed
// add a trailing edge
void ETFHPTDCChannel::AddTed(double t){
  vt.push_back(t);
} // end member function AddTed
// intended to subtract trigger time
void ETFHPTDCChannel::SubtractTrigger(unsigned bunchID){
  for(auto &t : vl) t = ETFMath::TimeToTrig(t, bunchID);
  for(auto &t : vt) t = ETFMath::TimeToTrig(t, bunchID);
} // end member functuion SubtractTrigger

void ETFHPTDCChannel::Print() const{
  cout << std::boolalpha << std::fixed << std::setprecision(6);

  cout << "\033[34;1mchannel ID: " << fChannelId << "\n\033[0m";
  cout << "is_V: " << fIs_V << endl;
  int i = 0;
  for(auto &t : vl) cout << "leading edge[" << i++ << "]: " << t << endl;
  i = 0;
  for(auto &t : vt) cout << "trailing edge[" << i++ << "]: " << t << endl;

  cout.unsetf(std::ios_base::floatfield);
  cout.unsetf(std::ios_base::boolalpha);
} // end member function Print
